﻿using System.Diagnostics;
using CSScriptLib;
using Newtonsoft.Json;

namespace Wargame_V3_1
{
    public class Operator
    {
        private Dictionary<string, dynamic> _oprAttris = new Dictionary<string, dynamic>();  // 存放算子属性
        private Dictionary<string, string> _oprModel = new Dictionary<string, string>();  // 存放算子模型，即各属性的值类型
        private Dictionary<string, dynamic> _oprMethods = new Dictionary<string, dynamic>(); // 存放算子的调用方法

        /// <summary>
        /// 构造方法：根据算子的模型和数据，构造算子对象
        /// </summary>
        /// <param name="model">算子模型，主要是属性类型</param>
        /// <param name="data">算子数据，主要在想定文件中</param>
        public Operator(Dictionary<string, string> model, Dictionary<string, object> data)
        {
            _oprModel = model;
            foreach (KeyValuePair<string, object> item in data)
            {
                if (_oprModel.ContainsKey(item.Key))
                {
                    string dataType = _oprModel[item.Key];
                    dynamic value = ChangeType.ConvertObject(item.Value, dataType);
                    _oprAttris.Add(item.Key, value);
                }
                else
                {
                    _oprAttris.Add(item.Key, item.Value);
                    Trace.TraceWarning($"{item.Key}的属性不在{_oprAttris["SubType"]}算子模型中。");
                }
            }
        }

        public dynamic GetAttri(string name)
        {
            if (_oprAttris.ContainsKey(name))
            {
                return _oprAttris[name];
            }
            else
            {
                Trace.TraceError($"{_oprAttris["SubType"]}算子没有属性{name}");
                return null;
            }
        }

        public void SetAttri(string name, dynamic value)
        {
            if (_oprModel.ContainsKey(name))
            {
                Type attriType = ChangeType.GetTypeByName(_oprModel[name]);  // 从算子模型中获得属性类型
                if (value == null)
                {
                    _oprAttris[name] = value;
                }
                else
                {
                    if (attriType == value.GetType())
                    {
                        _oprAttris[name] = value;
                    }
                    else if(value is object)  // 输入类型是object，类型变换后赋值
                    {
                        dynamic chg_value = ChangeType.ConvertObject(value, _oprModel[name]);
                        _oprAttris[name] = chg_value;
                    }
                    else
                    {
                        Trace.TraceError($"SetAttri赋值失败：数据类型不一致");
                    }
                }
            }
            else
            {
                Trace.TraceError($"SetAttri赋值失败，{_oprAttris["SubType"]}算子模型中没有属性{name}");
            }
        }

        public void SetMethod(string name, string code, string type = "cs")
        {
            if (type == "cs")
            {
                dynamic theMethod = CSScript.Evaluator.CreateDelegate<dynamic>(code);
                _oprMethods.Add(name, theMethod);
            }
            else
            {
                Trace.TraceWarning($"该类型{type}的代码目前不支持。");
            }
        }

        public dynamic InvokeMethod(string name, Dictionary<string, dynamic> param)
        {
            param["thisOpr"] = this;
            return _oprMethods[name](param);  // 所有的调用方法必须有输出，void方法输出null
        }

        public override string ToString()
        {
            return JsonConvert.SerializeObject(_oprAttris);
        }
    }
}
